from collections import deque
"""
@Project: pythonPro1
@Name: p14数据结构.py
@Author: linxin_liu
@Date: 2022/9/14 21:33
"""

# 一、列表作为堆栈使用
list1 = [1, 2, 3]
print("原始数据:", list1, end=' ')
list1.append(4)
print("栈添加数据:", list1, end=' ')
list1.pop()
print("栈顶弹出数据:", list1)

"""
二、列表作为队列使用
先入先出，但是效率不高，因为增、删元素要移动大量元素。
"""
queue1 = deque(["tom", "jerry", "jack"])
print("原始数据:", queue1, end=' ')
queue1.append("rose")
print("增加数据:", queue1, end='')
queue1.popleft()
print("弹出数据:", queue1)

"""
三、列表推导式
列表推导式提供了从序列创建列表的简单途径。
通常应用程序将一些操作应用于某个序列的每个元素，
用其获得的结果作为生成新列表的元素，或者根据确定的判定条件创建子序列。
每个列表推导式都在 for 之后跟一个表达式，然后有零到多个 for 或 if 子句。
返回结果是一个根据表达从其后的 for 和 if 上下文环境中生成出来的列表。
如果希望表达式推导出一个元组，就必须使用括号。 
"""
list2 = [2, 4, 6]
print('用列表推导式从列表生成一个新的列表:', [3*x for x in list2])
print('用列表推导式从列表生成一个新的列表:', [[x, x**2] for x in list2])
list3 = [' tom ', ' hello world ']
print('用列表推导式从列表生成一个新的列表(消除元素边缘空格):', [x.strip() for x in list3])
print('用列表推导式从列表生成一个新的列表:', [x for x in list2 if x > 2])
list4 = [1, 2, 3]
print('用列表推导式从列表生成一个新的列表(双循环):', [x*y for x in list2 for y in list4])
print('圆周率:', [str(round(355/113, i)) for i in range(1, 7)])

"""
四、嵌套列表解析
3X4的矩阵列表转换为4X3列表
"""
matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
]
# 方法一
# print([[row[i] for row in matrix] for i in range(4)])

# 方法二
# transposed = []
# for i in range(4):
#     transposed.append([row[i] for row in matrix])
# print(transposed)

'''
matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
]
'''
# 方法三
transposed = []
for i in range(4):  # the following 3 lines implement the nested listcomp
    transposed_row = []
    for row in matrix:
        # print(row, end=',')
        transposed_row.append(row[i])
    transposed.append(transposed_row)
    # print(end='==')
print('3X4的矩阵列表转换为4X3列表:', transposed)


"""
五、
使用 del 语句可以从一个列表中根据索引来删除一个元素，而不是值来删除元素。
这与使用 pop() 返回一个值不同。
可以用 del 语句从列表中删除一个切割，或清空整个列表（我们以前介绍的方法是给该切割赋一个空列表）。
"""

"""
六、
元组在输出时总是有括号的，以便于正确表达嵌套结构。
在输入时可能有或没有括号， 不过括号通常是必须的（如果元组是更大的表达式的一部分）。
"""

"""
七、
集合是一个无序不重复元素的集。基本功能包括关系测试和消除重复元素。
可以用大括号({})创建集合。注意：如果要创建一个空集合，你必须用 set() 而不是 {} ；
后者创建一个空的字典，下一节我们会介绍这个数据结构。
集合支持推导式
"""
set1 = {x for x in 'fioahouifghipruh' if x not in 'abcd'}
print('推导式生成的去重后的集合:', set1)

"""
八、字典
另一个非常有用的 Python 内建数据类型是字典。
序列是以连续的整数为索引，与此不同的是，字典以关键字为索引，关键字可以是任意不可变类型，通常用字符串或数值。
理解字典的最佳方式是把它看做无序的键=>值对集合。在同一个字典之内，关键字必须是互不相同。
一对大括号创建一个空的字典：{}。
"""
dict1 = {'a': 1, 'b': 2}
print('字典1：', dict1)
# 构造函数 dict() 直接从键值对元组列表中构建字典。如果有固定的模式，列表推导式指定特定的键值对：
dict2 = dict([('c', '3'), ('d', 4)])
print('字典2：', dict2)
dict3 = {x: x*2 for x in 'good'}
print('字典3：', dict3)
# 如果关键字只是简单的字符串，使用关键字参数指定键值对有时候更方便：
dict4 = dict(tom=1, jack=2)
print(dict4)

# 字典遍历技巧
# 在字典中遍历时，关键字和对应的值可以使用 items() 方法同时解读出来：
print('遍历字典的key和value: ', end='')
for k, v in dict3.items():
    print(k, v, end=', ')
# 在序列中遍历时，索引位置和对应值可以使用 enumerate() 函数同时得到：
print()
print('序列中遍历时，得到索引位置和对应值:',)
for i, v in enumerate(['jack', 'jerry', 'tom']):
    print(i, v, end=', ')
print()
print()

# 同时遍历两个或更多的序列，可以使用 zip() 组合：
print("同时遍历两个或更多的序列，可以使用 zip() 组合")
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
    print('What is your {0}?  It is {1}.'.format(q, a))
# 要反向遍历一个序列，首先指定这个序列，然后调用 reversed() 函数：
for i in reversed(range(1, 10, 2)):
    print(i, end=' ')


# 要按顺序遍历一个序列，使用 sorted() 函数返回一个已排序的序列，并不修改原值：
print()

basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
    print(f, end=' ')



